package new_api

import (
	"encoding/json"
	"fmt"
	"gin_study_blog/common/http"
	"gin_study_blog/service/redis"
	"github.com/fatih/structs"
	"github.com/gin-gonic/gin"
	"io"
	netHttp "net/http"
	"strconv"
	"strings"
	"time"
)

type params struct {
	ID   string `json:"id"`
	Size int    `json:"size"`
}

type header struct {
	Signaturekey string `form:"signaturekey" struct:"signaturekey"`
	Version      string `form:"version" struct:"version"`
	UserAgent    string `form:"User_Agent" struct:"User_Agent"`
}

type NewResponse struct {
	Code int             `json:"code"`
	Data []redis.NewData `json:"data"`
	Msg  string          `json:"msg"`
}

const newAPI = "https://api.codelife.cc/api/top/list"
const timeout = 2 * time.Second

func (NewApi) NewListView(c *gin.Context) {
	var cr params
	var headers header
	err := c.ShouldBindJSON(&cr)
	err = c.ShouldBindHeader(&headers)
	if err != nil {
		http.FailWithCode(http.ParamsError, c)
		return
	}
	if cr.Size == 0 {
		cr.Size = 1
	}
	key := fmt.Sprintf("%s-%d", cr.ID, cr.Size)
	newsData, _ := redis.GetNews(key)
	if len(newsData) != 0 {
		http.IsOkWithData(newsData, c)
		return
	}
	httpResponse, err := Post(newAPI, cr, structs.Map(headers), timeout)
	if err != nil {
		http.FailWithMessage(err.Error(), c)
		return
	}
	var response NewResponse
	byteData, err := io.ReadAll(httpResponse.Body)
	err = json.Unmarshal(byteData, &response)
	if err != nil {
		http.FailWithMessage(err.Error(), c)
		return
	}
	if response.Code != 200 {
		http.FailWithMessage(response.Msg, c)
		return
	}
	err = redis.SetNews(key, response.Data)
	fmt.Println(err)
	http.IsOkWithData(response.Data, c)
}

func Post(url string, data any, header map[string]interface{}, duration time.Duration) (resp *netHttp.Response, err error) {
	reqParam, _ := json.Marshal(data)
	reBody := strings.NewReader(string(reqParam))
	httpReq, err := netHttp.NewRequest("POST", url, reBody)
	if err != nil {
		return
	}
	httpReq.Header.Add("Content-Type", "application/json")
	for key, val := range header {
		switch v := val.(type) {
		case string:
			httpReq.Header.Add(key, v)
		case int:
			httpReq.Header.Add(key, strconv.Itoa(v))
		}
	}

	client := netHttp.Client{
		Timeout: duration,
	}

	// DO HTTP 请求
	resp, err = client.Do(httpReq)
	return resp, nil
}
